package com.marion.mzuul.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collections;

@Service
public class SentinelService {

    public static final String LIMIT = "limit";

    @PostConstruct
    public void init() {
        // 流控规则：1s的QPS超过2进行限流
        FlowRule fr = new FlowRule();
        fr.setResource(LIMIT);
        fr.setCount(2);
        fr.setGrade(RuleConstant.FLOW_GRADE_QPS);
        fr.setStrategy(RuleConstant.STRATEGY_DIRECT);

        // 熔断规则：5s内接口异常超过5次时熔断
        DegradeRule dr = new DegradeRule();
        dr.setResource(LIMIT);
        dr.setCount(5);
        dr.setMinRequestAmount(5);
        dr.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        dr.setTimeWindow(5);

        FlowRuleManager.loadRules(Collections.singletonList(fr));
        DegradeRuleManager.loadRules(Collections.singletonList(dr));

    }

    /**
     * 限流：2QPS/s
     */
    @SentinelResource(value = LIMIT, blockHandler = "limitBlockHandler", fallback = "limitFallback")
    public String limit(long uid) {
        if (uid == 0) {
            throw new NullPointerException();
        }
        return "success";
    }

    public String limitBlockHandler(long uid, BlockException exp) {
        exp.printStackTrace();
        return uid + " qps > 2/s, limited";
    }

    public String limitFallback(long uid, BlockException exp) {
        exp.printStackTrace();
        return uid + " qps > 2/s, limited";
    }
}
